﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Activation;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Services;
using System.Text;
using System.Threading.Tasks;

namespace Aragorn.SOA.Infratructure.AOP
{
    public class AOPProxy:RealProxy,IProxyDI
    {
        private MethodInfo method;
        MarshalByRefObject  _target;
        private IInterception _interception = null;


        public AOPProxy(Type serverType,MarshalByRefObject target):base(serverType)
        {
            this._target = target;
            method = serverType.GetMethod("Set", BindingFlags.NonPublic | BindingFlags.Instance);
        }

        //覆写Invoke，处理RealProxy截获的各种消息,
        public override IMessage Invoke(IMessage msg)
        {
            IMethodReturnMessage methodReturnMessage = null;
            IMethodCallMessage methodCallMessage = msg as IMethodCallMessage;//Check whether the message is method call message.
            if (methodCallMessage!=null)
            {
                IConstructionCallMessage constructionCallMessage = methodCallMessage as IConstructionCallMessage;
                if (constructionCallMessage!=null)
                {
                    RealProxy defaultProxy = RemotingServices.GetRealProxy(_target);
                    defaultProxy.InitializeServerObject(constructionCallMessage);
                    methodReturnMessage = EnterpriseServicesHelper.CreateConstructionReturnMessage(constructionCallMessage, (MarshalByRefObject)GetTransparentProxy());
                }
                else
                {
                    _interception.PreInvoke();
                    try
                    {
                        methodReturnMessage = RemotingServices.ExecuteMessage(_target, methodCallMessage);
                    }
                    catch
                    {
                    }
                    if (methodReturnMessage.Exception != null)
                    {
                        _interception.ExceptionHandle();
                    }
                    else
                    {
                        _interception.PostInvoke();
                    }
                }

            }
            return methodReturnMessage;
        }

        public void InterceptionDI(IInterception interception)
        {
            _interception = interception;
        }
    }
}
